package com.goodfox.web.generic.provide.service.impl;

import java.io.OutputStream;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.stereotype.Service;

import com.goodfox.web.generic.provide.annotation.DbField;
import com.goodfox.web.generic.provide.entity.ColumnField;
import com.goodfox.web.generic.provide.service.ExcelTemplateService;
import com.goodfox.web.generic.provide.util.DateUtil;
import com.goodfox.web.generic.provide.util.ParameterUtil;
import com.sun.xml.internal.messaging.saaj.packaging.mime.internet.MimeUtility;

/**
 * ExcelTemplateService的实现类
 * 
 * @author qin gt
 * 
 * @param <T>
 */
@Service("excelTemplateService")
public class ExcelTemplateServiceImpl implements ExcelTemplateService {

	/** log4j日志器 */
	private Logger logger = Logger.getLogger(ExcelTemplateServiceImpl.class);
	
	/**
	 * 根据list导出excel文件
	 * @param request 请求对象
	 * @param response 相应对象
	 * @param fieldList 表头标题
	 * @param entityList 实体列表
	 */
	@Override
	public void webExpWorkbook(HttpServletRequest request, HttpServletResponse response, List<ColumnField> fieldList,List entityList) {
		HSSFWorkbook workbook = createWorkbook(fieldList, entityList);
		try {
			OutputStream out = response.getOutputStream();
			request.setCharacterEncoding("UTF-8");
			response.setCharacterEncoding("UTF-8");
			response.setContentType("application/msexcel");
			response.setHeader("Content-disposition", "attachment;"+ transformationFileName(request));
			workbook.write(out);
			out.flush();
		} catch (Exception ex) {
			logger.error("根据list导出excel文件出错", ex);
		}
	}

	/**
	 * 根据list创建excel文件
	 * @param headers 表头标题
	 * @param fieldList 表头标题
	 * @param entityList 实体列表
	 * @return
	 */
	@Override
	public HSSFWorkbook createWorkbook(List<ColumnField> fieldList,List entityList) {
		logger.debug("进入创建List的方法");

		HSSFWorkbook workbook = new HSSFWorkbook();
		HSSFSheet sheet = workbook.createSheet("sheet");
		for(int i=0;i<fieldList.size();i++){
			ColumnField cf=fieldList.get(i);
			cf.setWriteSort(i);
		}
		HSSFRow row0 = sheet.createRow(0);
		for (int i = 0; i < fieldList.size(); i++) {
			row0.createCell(i).setCellValue(fieldList.get(i).getShowName());
		}
		int index=1;
		for(int i=0;i<entityList.size();i++){
			index=fillCellValue(sheet, entityList.get(i), fieldList, index);
		}
		return workbook;
	}

	/**
	 * 根据list导出excel文件
	 * @param request
	 * @param response
	 * @param c
	 * @param entityList
	 */
	@Override
	public void webExpWorkbook(HttpServletRequest request, HttpServletResponse response,Class c,List entityList) {
		HSSFWorkbook workbook =createWorkbook(c,entityList);
		try {
			OutputStream out = response.getOutputStream();
			request.setCharacterEncoding("UTF-8");
			response.setCharacterEncoding("UTF-8");
			response.setContentType("application/msexcel");
			response.setHeader("Content-disposition", "attachment;"+ transformationFileName(request));
			workbook.write(out);
			out.flush();
		} catch (Exception ex) {
			logger.error("根据list导出excel文件出错", ex);
		}
	}
	

	/**
	 * 根据list创建excel文件
	 * @param c
	 * @param entityList
	 * @return
	 */
	public HSSFWorkbook createWorkbook(Class c,List entityList){
		HSSFWorkbook workbook = new HSSFWorkbook();
		HSSFSheet sheet = workbook.createSheet("sheet");
		List<ColumnField> fieldList=new ArrayList<ColumnField>();
		fillFieldList(c,fieldList,false);
		for(int i=0;i<fieldList.size();i++){
			ColumnField cf=fieldList.get(i);
			cf.setWriteSort(i);
		}
		HSSFRow row0=sheet.createRow(0);
		for(ColumnField cf:fieldList){
			row0.createCell(cf.getWriteSort()).setCellValue(cf.getShowName());
		}
		int index=1;
		for(int i=0;i<entityList.size();i++){
			index=fillCellValue(sheet, entityList.get(i), fieldList, index);
		}
		return workbook;
	}

	
	private int fillCellValue(HSSFSheet sheet,Object obj,List<ColumnField> fieldList,int index){
		try{
			Field[] fileds = obj.getClass().getDeclaredFields();
			for(Field f:fileds){
				f.setAccessible(true);
				DbField df=f.getAnnotation(DbField.class);
				if(df.export()){
					if(df.javaType().equals("EntityList")){
						List list=(List)f.get(obj);
						if(list!=null && list.size()>0){
							for(int i=0;i<list.size();i++){
								for(ColumnField cf:fieldList){
									if(df.subClass().equals(cf.getSubClass())){
										index=fillCellValue(sheet,list.get(i),fieldList,index);
										break;
									}
								}
							}
						}else{
							index++;
						}
					}else{
						for(ColumnField cf:fieldList){
							if(f.getName().equals(cf.getFiledName())){
								HSSFRow row=sheet.getRow(index);
								if(row==null){
									row=sheet.createRow(index);
								}
								String value=getFieldValue(cf.getFiledName(), obj);
								row.createCell(cf.getWriteSort()).setCellValue(value);
								if(cf.getWriteSort()+1==fieldList.size()){
									index++;
								}
								break;
							}
						}
					}
				}
			}
		}catch(Exception ex){
			logger.error("填充单元格异常",ex);
		}
		return index;
	}

	private void fillFieldList(Class c,List<ColumnField> fieldList,boolean subType){
		for(Field f:c.getDeclaredFields()){
			DbField df=f.getAnnotation(DbField.class);
			if(df!=null){
				if(df.meaning()){
					if(df.export()){
						if(df.javaType().equals("EntityList")){
							fillFieldList(df.subClass(),fieldList,true);
						}else{
							ColumnField cf=null;
							if(subType){
								cf=new ColumnField(df.comment(),f.getName(),c);
							}else{
								cf=new ColumnField(df.comment(),f.getName());
							}
							fieldList.add(cf);
						}
					}
				}
			}
		}
	}
	
	private String getFieldValue(String fieldName, Object obj) {
		String value = "";
		try {
			Field filed = obj.getClass().getDeclaredField(fieldName);
			filed.setAccessible(true);
			if(filed!=null && filed.get(obj)!=null){
				DbField df=filed.getAnnotation(DbField.class);
				if (filed.get(obj).getClass().equals(Date.class)) {
					value = DateUtil.format((Date)filed.get(obj),df.pattern());
				}else if (filed.get(obj).getClass().equals(Timestamp.class)) {
					value = DateUtil.format((Date)filed.get(obj),df.pattern());
				} else {
					value = String.valueOf(filed.get(obj));
				}
			}
		} catch (Exception ex) {
			logger.error("获取字段值异常", ex);
		}
		return value;
	}
	
	private String transformationFileName(HttpServletRequest request){
		String fileName="excel.xls";
		try{
			String userAgent=request.getHeader("User-Agent");
			if(userAgent!=null){
				String excelName=ParameterUtil.getReqParaDecodeValue(request, "excelName");
				userAgent=userAgent.toLowerCase();
				if(userAgent.indexOf("msie")>=0){
					fileName="filename="+URLEncoder.encode(excelName, "UTF-8");
				}else if(userAgent.indexOf("firefox")>=0){
					fileName="filename="+MimeUtility.encodeText(excelName, "UTF-8", "B");
				}else if(userAgent.indexOf("safari")>=0){
					fileName="filename="+new String(excelName.getBytes("UTF-8"),"ISO-8859-1");
				}else if(userAgent.indexOf("opera")>=0){
					fileName="filename*=UTF8\""+URLEncoder.encode(excelName, "UTF-8");
				}
			}
		}catch(Exception ex){
			logger.error("转换文件名称异常", ex);
		}
		return fileName;
	}

}
